home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-09-12 | 7.2 KB | 244 lines | [TEXT/CCL2] |
- ;;; -*- Mode: LISP; Package: THINK-C; Syntax: Common-lisp; Base: 10; -*-
- ;;; Thr Nov 14 1991 by Guillaume Cartier <cartier@math.uqam.ca>
- ;;; think-c.lisp
- ;;;
- ;;; *****************************************************************
- ;;; General License Agreement and Lack of Warranty ******************
- ;;; *****************************************************************
- ;;;
- ;;; This software is distributed in the hope that it will be useful (both
- ;;; in and of itself), but WITHOUT ANY WARRANTY. The author does not accept
- ;;; responsibility to anyone for the consequences of using it or for whether
- ;;; it serves any particular purpose or works at all. No warranty is made
- ;;; about the software or its performance.
- ;;;
- ;;; The current version of this software may be obtained by anonymous ftp
- ;;; from cambridge.apple.com in the directory pub/MCL/CONTRIB.
- ;;;
- ;;; Please send bug reports, comments, questions and suggestions to
- ;;; cartier@math.uqam.ca. I would also appreciate receiving any changes
- ;;; or improvements you may make.
- ;;;
- ;;; *****************************************************************
- ;;; ThinkC interface ************************************************
- ;;; *****************************************************************
- ;;;
- ;;; This ThinkC interface consist of some lisp files and C header
- ;;; files, enabling one to easily use ThinkC functions in MCL. An
- ;;; example is also provided.
- ;;;
- ;;; Very special thanks to the MCL team, they have always been very
- ;;; generous of their time in responding promptly to any questions I had.
- ;;;
- ;;; *****************************************************************
- ;;; Revision History ************************************************
- ;;; *****************************************************************
- ;;;
- ;;; 25/01/91 - Posted the code for the first time at cambridge.
- ;;; 14/11/91 - Converted the code to MCL2.0b1.
- ;;;
-
-
- (require :ff)
- (provide :think-c)
-
- (defpackage "THINK-C"
- (:use "COMMON-LISP" "CCL")
- (:import-from "CCL" "DEF-MACTYPE" "MAKE-MACTYPE" "%VREFLET")
- (:export "*THINK-C-FOLDER*"
- "DEFCMODULE"
- "DEFAULT-RESOURCE-FILE"
- "LOAD-CMODULE"
- "CLOSE-CMODULE"
- "%ALLOCATE-DOUBLE"
- "%MAKE-DOUBLE"
- "%GET-DOUBLE"
- "%PUT-DOUBLE"))
-
- (in-package "THINK-C")
-
-
- ;;; ***********************
- ;;; Global stuff **********
- ;;; ***********************
-
-
- (defvar *THINK-C-FOLDER*
- "think-c:")
-
- (defvar *CMODULE-RESOURCE-TYPE*
- "TCCD")
-
- (defvar *CMODULES-TABLE*
- (make-hash-table))
-
- (defvar *CMODULES*
- nil)
-
-
- (defstruct CMODULE
- name
- variables
- functions
- resource-file
- refnum)
-
-
- (defun GET-CMODULE (module-name)
- (or (gethash module-name *cmodules-table*)
- (error "Unknown C module ~a ." module-name)))
-
-
- ;;; *****************************
- ;;; CModule definition **********
- ;;; *****************************
-
-
- (defmacro DEFCMODULE (name &key variables functions
- (resource-file (default-resource-file name)))
- `(progn
- (defvar ,name)
- (setf (gethash ',name *cmodules-table*)
- (make-cmodule
- :name ',name
- :variables ',variables
- :functions ',(mapcar (function car) functions)
- :resource-file ,resource-file))
- (pushnew ',name *cmodules*)
- ,@(mapcar (function
- (lambda (symb)
- `(defvar ,symb)))
- variables)
- ,@(mapcan (function
- (lambda (spec)
- (apply (function expand-function-spec)
- (cons name spec))))
- functions)
- ',name))
-
-
- (defun EXPAND-FUNCTION-SPEC (loader symb argstype &optional restype)
- (let* ((args (loop for arg in argstype
- collect (if (keywordp arg)
- (copy-symbol arg)
- (intern (write-to-string arg)))))
- (lispargs (loop for x in argstype for y in args
- for type = (if (keywordp x) x (second x))
- when (eq type :lisp) collect y)))
- (list
- `(defvar ,symb)
- `(defun ,symb ,args
- (%vreflet ,(mapcar (function list) lispargs lispargs)
- (ff-call ,symb :a4 ,loader
- ,@(loop for x in (reverse args)
- collect :ptr collect x)
- ,(or restype :novalue)))))))
-
-
- (defun DEFAULT-RESOURCE-FILE (name)
- (merge-pathnames
- *think-c-folder*
- (symbol-name name)))
-
-
- ;;; *********************
- ;;; The loader **********
- ;;; *********************
-
-
- (defun LOADER-IMPORT (loader symb)
- (with-pstrs ((str (symbol-name symb)))
- (let ((add (ff-call loader :a4 loader :ptr str :a0)))
- (if (%null-ptr-p add)
- (error "Undefined C function ~a ." symb)
- (set symb add)))))
-
-
- (defun LOAD-CMODULE (module-name)
- (let ((module (get-cmodule module-name)))
- (setf (cmodule-refnum module)
- (open-resource-file (truename (cmodule-resource-file module))))
- (let ((res (get-resource *cmodule-resource-type* (symbol-name module-name))))
- (cond
- ((null res)
- (error "Can't find the C module ~a ." module-name))
- (t (#_DetachResource res)
- (let ((loader (%get-ptr res)))
- (set module-name loader)
- (dolist (symb (cmodule-variables module)) (loader-import loader symb))
- (dolist (symb (cmodule-functions module)) (loader-import loader symb))))))))
-
-
- (defun CLOSE-CMODULE (module-name)
- (close-resource-file
- (cmodule-refnum (get-cmodule module-name))))
-
-
- (def-load-pointers RESTORE-CMODULES ()
- (dolist (cmodule *cmodules* t)
- (apply (function load-cmodule) cmodule)))
-
-
- ;;; ***************************
- ;;; ThinkC's doubles **********
- ;;; ***************************
-
-
- (defun (setf %GET-DOUBLE) (data pointer &optional (offset 0))
- (%put-double pointer data offset))
-
-
- (defun %ALLOCATE-DOUBLE ()
- (#_NewPtr 12))
-
- (defun %MAKE-DOUBLE (float)
- (let ((ptr (%allocate-double)))
- (setf (%get-double ptr) float)
- ptr))
-
-
- (defun %GET-DOUBLE (pointer &optional (offset 0))
- (let ((ptr (%inc-ptr pointer offset)))
- (%put-word ptr (%get-word ptr) 2)
- (ccl::%get-x2float (%inc-ptr ptr 2))))
-
- (defun %PUT-DOUBLE (pointer float &optional (offset 0))
- (let ((ptr (%inc-ptr pointer offset)))
- (ccl::%float2x (float float) (%inc-ptr ptr 2))
- (%put-word ptr (%get-word ptr 2))))
-
-
- ;;
- ;; If you're using MCL2.0b3 or upwards, you can use the following
- ;; definition to ease working with doubles. In fact, you could probably
- ;; use it also in MCL2.0b1 with small changes (MCL2.0b1 does'nt recognize
- ;; the :access-operator keyword option to DEF-MACTYPE).
- ;;
-
- (unless (search "2.0b1" (lisp-implementation-version))
-
- (def-mactype :DOUBLE
- (make-mactype
- :name :double
- :record-size 12
- :access-operator '%get-double)))
-
-
- ;;; **************************
- ;;; Resources stuff **********
- ;;; **************************
-
-
- (defun OPEN-RESOURCE-FILE (file)
- (with-pstrs ((pf (mac-namestring (truename file))))
- (#_OpenResFile pf)))
-
- (defun CLOSE-RESOURCE-FILE (refnum)
- (#_CloseResFile refnum))
-
-
- (defun GET-RESOURCE (type name)
- (let ((res (with-pstrs ((ps name))
- (#_GetNamedResource type ps))))
- (unless (%null-ptr-p res) res)))
-